<?php
/**
 * 
 * +------------------------------------------------------------+
 * @category MCache 
 * +------------------------------------------------------------+
 * Memcache数据缓存管理类，使用Memcache来管理内存，在内存中，对数据的进行存取、删除等操作
 * +------------------------------------------------------------+
 *
 * @author anzai <236049524@qq.com>
 * @copyright http://www.judianyun.com 2012
 * @version 1.0
 *
 * Modified at : 2012-02-16 11:25:35
 *
 */
class MCache extends Cache {
	//仅当存储空间中不存在键相同的数据时才保存一个数据到服务器上
	const MEMCACHE_ADD = 'a';
	
	//无论何时都可以保存一个数据到服务器上
	const MEMCACHE_SET = 's';
	
	//将服务器上已存在的数据进行替换，若不存在则不进行保持数据操作
	const MEMCACHE_REPLACE = 'r';
	
	///当前正在连接的对象ID号
	public $_linkId = 0;
	
	///一组Memcached对象
	private $_memLink = null;
	
	///相关配置
	private $_config = array(array(
		'host' => '127.0.0.1',  //服务器地址
		'port' => '11211',      //开放的端口号
		'timeout' => '60',      //在内存中的生存期，默认60秒
		'pconnect' => false,    //是否使用永久连接
		'prefix' => 'mc_'   	//前缀
	));
	
	function __construct($config=null){
		if (!class_exists('Memcache')){
			throw new E(Helper::L('CLS_MCACHE_MODULE'),EXCEPTION_T_APP);
		}
		$this->_memLink===null && $this->connect($config);
	}
	
	//清除服务器中内存中的所有数据
	function clear(){
		if (!$this->_memLink[$this->_linkId]) return ;
		try {
			if(!$this->_memLink[$this->_linkId]->flush())
				throw new E(sprintf(Helper::L('CLS_MCACHE_CLEAR'),'Memcache',$this->_config[$this->_linkId]['host'].':'.$this->_config[$this->_linkId]['port']),EXCEPTION_T_APP);
		}catch (E $e){
			$e->getMsg();
		}
		
		return $this;
	}
	
	//关闭连接
	function close($linkId=null){
		try{ //未指定要关闭的服务端，则默认关闭所有已经连接的服务端
			if($linkId===null && !empty($this->_memLink)){
				foreach ($this->_memLink as $id=>$link){
					$msg = $link && !$link->close() ? sprintf(Helper::L('CLS_MCACHE_CLOSE_SERVER'),'Memcache',$this->_config[$id]['host'].':'.$this->_config[$id]['port']) : '';
				}
			}else{
				$linkId = (int) $linkId;
				$msg = $this->_memLink[$linkId] && !$this->_memLink[$linkId]->close() ? sprintf(Helper::L('CLS_MCACHE_CLOSE_SERVER'),$this->_config[$linkId]['host'].':'.$this->_config[$linkId]['port']) : '';
			}
			if (!empty($msg))
				throw new E($msg,EXCEPTION_T_APP);
		}catch (E $e){
			$e->getMsg();
		}
	}
	
	/**
	 * 
	 * +------------------------------------------------------------+
	 * @name connect
	 * +------------------------------------------------------------+
	 * 连接Memcach服务端
	 * +------------------------------------------------------------+
	 *
	 * @author anzai <236049524@qq.com>
	 * @version 1.0
	 *
	 * @example
	 *
	 * @param mixed $config 相关配置，可为空
	 * @param int $linkId   存储对象的ID号
	 *
	 */
	function connect($config='',$linkId=0){
		$this->_linkId = $linkId;
		if(isset($this->_memLink[$linkId]))
			return $this;
			
		$config = empty($config) ? $this->_config[0] : $config;
		$this->_config[$linkId] = $config;
		try{
			$this->_memLink[$linkId] = new Memcache;
			
			$func = $config['pconnect'] ? 'pconnect' : 'connect';
			if(!@$this->_memLink[$linkId]->$func($config['host'],$config['port']))
				throw new E(sprintf(Helper::L('CLS_MCACHE_CONNECT_SERVER'),$config['host'].':'.$config['port'],'Memcache'),EXCEPTION_T_APP);
			return $this;
		}catch(E $e){
			$e->getMsg();
		}
		
		return null;
	}
	
	//从服务器上删除指定数据
	function delete($key,$timeout=0){
		if (!$this->_memLink[$this->_linkId]) return ;
		$key = md5($this->_config[$this->_linkId]['prefix'].$key);
		$this->_memLink[$this->_linkId]->delete($key,$timeout);
		return $this;
	}
	
	//从服务器上获取数据，可同时传入多个参数，以获取多个
	function get(){
		if (!$this->_memLink[$this->_linkId]) return ;

		$args = func_get_args();
		if (!empty($args)){
			if(count($args)==1)
				$tmp = $this->_memLink[$this->_linkId]->get(md5($this->_config[$this->_linkId]['prefix'].$args[0]));
			else{
				foreach ($args as $key){
					$tmp[$key] =  $this->_memLink[$this->_linkId]->get(md5($this->_config[$this->_linkId]['prefix'].$key));
				}
			}
		}else{
			$tmp = null;
		}
		
		return $tmp;
	}

	/**
	 * 
	 * +------------------------------------------------------------+
	 * @name set
	 * +------------------------------------------------------------+
	 * 将数据写入内存中，支持将数组保持到服务器中
	 * +------------------------------------------------------------+
	 *
	 * @author anzai <236049524@qq.com>
	 * @version 1.0
	 *
	 * @example
	 *
	 * @param  $key   保存数据的名称
	 * @param  $value 对应的值
	 * @param  $mode  写入内存的使用模式，有三种模式（self::MEMCACHE_ADD、self::MEMCACHE_REPLACE、self::MEMCACHE_SET）
	 * @param  $mark  标记默认为0或MEMCACHE_COMPRESSED
	 * @return 
	 *
	 */
	function set($key,$value,$mode='',$mark=0){
		if (!$this->_memLink[$this->_linkId]) return $this;
		switch ($mode){
			case self::MEMCACHE_ADD:
				$msg = Helper::L('CLS_MCACHE_WRITE');
				$func = 'add';
				break;
			case self::MEMCACHE_REPLACE:
				$msg = Helper::L('CLS_MCACHE_REPLACE');
				$func = 'replace';
				break;
			default:
				$msg = Helper::L('CLS_MCACHE_WRITE');
				$func = 'set';
				break;
		}
		$config = $this->_config[$this->_linkId];
		$key = md5($config['prefix'].$key);
		try{
			if(!$this->_memLink[$this->_linkId]->$func($key,$value,$mark,$config['timeout']))
				throw new E($msg.sprintf(Helper::L('CLS_MCACHE_RUNNING'),$config['host'].':'.$config['port'],'Memcache'),EXCEPTION_T_APP);
		}catch (E $e){
			$e->getMsg();
		}
		
		return $this;
	}
	
	function __destruct(){
		$this->close();
	}
}

?>